﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Afvanding;
using Afvanding.RefToPumpService;
namespace Afvanding
{
    public delegate void RainValue(int stationId, DateTime date, double value, double level);
    public delegate void DrainValue(int stationId, int pumpId, DateTime date, double value, double level);
    //public delegate void WaterLevel(int stationId, DateTime date, double value);

    class WaterThread
    {
        private WaterMonitor _m;
        private readonly Random _random;
        private DateTime _now;
        private int _min, _max, _requestFrequency;
        public bool IsRaining;
        private volatile bool _simulate; //start/stop simulator http://msdn.microsoft.com/en-us/library/7a2f3ay4(v=vs.90).aspx
        private List<Pump> _pumps;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="monitor">Monitor is needed to access events</param>
        /// <param name="pumps"></param>
        /// <param name="minRainValue">min value for rain</param>
        /// <param name="maxRainValue">max value for rain</param>
        /// <param name="requestFrequencyInMinut"></param>
        public WaterThread(WaterMonitor monitor, /*Dictionary<int, double>*/List<Pump> pumps, int minRainValue, int maxRainValue, int requestFrequencyInMinut)
        {
            _m = monitor;
            _pumps = pumps;
            _min = minRainValue;
            _max = maxRainValue;
            _requestFrequency = requestFrequencyInMinut * 1000;
            _random = new Random();
            _now = DateTime.Now;
            IsRaining = false;
            _simulate = false;
        }

        public void Rain()
        {
            int i = 0, max = _max;

            while (_simulate)
            {
                if (IsRaining) //already raining, continue or stop rain?
                {
                    if (_random.Next(0, 5) < 4) { i = _random.Next(1, max); }
                    else { IsRaining = false; }
                }
                else
                {
                    if (_random.Next(0, 10) > 8) //the chance of rain is rather small compaired to the dry hours
                    {
                        i = _random.Next(_min, _max);
                        max = i;
                        IsRaining = true;
                    }
                    else { IsRaining = false; }
                }
                _m.Enqueue(i);
                Thread.Sleep(_requestFrequency);
            }
        }

        public void Drain(object pumpId)
        {
            int count = 0;
            int index = -1;
            foreach (Pump pump in _pumps)
            {
                if (pump.Id == (int)pumpId)
                {
                    index = count;
                    break;
                }
                count++;
            }

            if (index != -1)
            {
                while (_simulate && _pumps[index].Status == 1)
                {
                    _m.Dequeue(_pumps[index].Id, _pumps[index].Capacity);
                    Thread.Sleep(_requestFrequency);
                }
            }
        }

        public void Start()
        {
            _m.IsRunning = true;
            _simulate = true;
            ChangeStates(_pumps, 1);
        } //start all
        public void StartPump(int id)
        {
            _m.IsRunning = true;
            _simulate = true;
            ChangeStatus(id, 1);
        } //start pump
        public void Pause()
        {
            _m.IsRunning = false;
        } //pause all
        public void PausePump(int id)
        {
            ChangeStatus(id, 0);
        } //pause pump
        public void Resume() { _m.IsRunning = true; } //resume all
        public void ResumePump(int id) { ChangeStatus(id, 1); } //resume pump
        public void Stop() { _m.IsRunning = false; _simulate = false; } //stop all
        public void StopPump(int id) { ChangeStatus(id, 0); } //stop pump

        private void ChangeStatus(int id, int status)
        {
            foreach (Pump pump in _pumps)
            {
                if (pump.Id == id) { pump.Status = status; }
                break;
            }
        }
        private void ChangeStates(List<Pump> pumps, int status)
        {
            foreach (Pump t in pumps.SelectMany(pump => _pumps.Where(t => t.Id == pump.Id))) { t.Status = status; }
        }
    }
}